using DapperExtensionsNew.Configuration;
using System;
using System.Linq;
using System.Linq.Expressions;
using System.Reflection;

namespace DapperExtensionsNew.Queryable.Analyzers
{
	public class Contains : Where
	{
		protected static readonly string Suffix = "s";

		protected override bool IsSatisfied(Context context, PropertyInfo queryProperty)
		{
			if (!queryProperty.Name.EndsWith(Suffix) || !queryProperty.PropertyType.IsArray)
			{
				return false;
			}
			Type elementType = queryProperty.PropertyType.GetElementType();
			if (elementType == typeof(int) || elementType == typeof(long) || elementType == typeof(string))
			{
				string targetModelPropertyName = queryProperty.Name.Substring(0, queryProperty.Name.Length - Suffix.Length);
				PropertyInfo propertyInfo = context.ModelProperties.FirstOrDefault((PropertyInfo x) => x.Name == targetModelPropertyName);
				if (propertyInfo == null)
				{
					return false;
				}
				if (propertyInfo.PropertyType == elementType)
				{
					return true;
				}
				Type propertyType = propertyInfo.PropertyType;
				if (propertyType.IsGenericType && propertyType.GetGenericTypeDefinition() == typeof(Nullable<>))
				{
					return propertyType.GetGenericArguments().First() == elementType;
				}
			}
			return false;
		}

		protected override Expression GetWhereClause(Context context, PropertyInfo queryProperty)
		{
			string text = queryProperty.Name.Substring(0, queryProperty.Name.Length - Suffix.Length);
			string columnName = GetColumnName(context.ModelType, text);
			MemberExpression memberExpression = Expression.Property(context.QueryExpression, queryProperty);
			ConstantExpression constantExpression = Expression.Constant("@" + text + Suffix);
			SqlDatabaseOptions sqlDatabaseOptions = SqlDatabaseOptionsFactory.GetSqlDatabaseOptions(context.Analyzer);
			string startDelimiter = sqlDatabaseOptions.StartDelimiter;
			string endDelimiter = sqlDatabaseOptions.EndDelimiter;
			Expression stringParam = ConcatExpression(Expression.Constant(" AND " + startDelimiter + columnName + endDelimiter + " IN "), constantExpression);
			BinaryExpression left = Expression.NotEqual(memberExpression, Expression.Constant(null));
			BinaryExpression right = Expression.GreaterThan(Expression.ArrayLength(memberExpression), Expression.Constant(0));
			BlockExpression ifTrue = Expression.Block(CallStringBuilderAppend(context.SqlExpression, stringParam), CallAddParameters(context.ParametersExpression, constantExpression, memberExpression));
			return Expression.Block(Expression.IfThen(Expression.AndAlso(left, right), ifTrue));
		}
	}
}
